// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package strconv

import "math/bits"

const fastSmalls = true // 为小整数启用快速路径

// FormatUint返回给定基中i的字符串表示形式，
// 为2<=base<=36。结果使用小写字母“a”到“z”
// 表示大于等于10的数字值。
func FormatUint(i uint64, base int) string {
	if fastSmalls && i < nSmalls && base == 10 {
		return small(int(i))
	}
	_, s := formatBits(nil, i, base, false, false)
	return s
}

// formatt返回给定基中i的字符串表示形式，
// for 2<=base<=36。结果使用小写字母“a”到“z”
// 表示大于等于10的数字值。
func FormatInt(i int64, base int) string {
	if fastSmalls && 0 <= i && i < nSmalls && base == 10 {
		return small(int(i))
	}
	_, s := formatBits(nil, uint64(i), base, i < 0, false)
	return s
}

// Itoa相当于FormatInt（int64（i），10）。
func Itoa(i int) string {
	return FormatInt(int64(i), 10)
}

// AppendInt将FormatInt生成的整数i的字符串形式
// 追加到dst，并返回扩展缓冲区。
func AppendInt(dst []byte, i int64, base int) []byte {
	if fastSmalls && 0 <= i && i < nSmalls && base == 10 {
		return append(dst, small(int(i))...)
	}
	dst, _ = formatBits(dst, uint64(i), base, i < 0, true)
	return dst
}

// AppendUint将FormatUint生成的无符号整数i的字符串形式
// 追加到dst，并返回扩展缓冲区。
func AppendUint(dst []byte, i uint64, base int) []byte {
	if fastSmalls && i < nSmalls && base == 10 {
		return append(dst, small(int(i))...)
	}
	dst, _ = formatBits(dst, i, base, false, true)
	return dst
}

// small返回0<=i<nSmalls的i的字符串。
func small(i int) string {
	if i < 10 {
		return digits[i : i+1]
	}
	return smallsString[i*2 : i*2+2]
}

const nSmalls = 100

const smallsString = "00010203040506070809" +
	"10111213141516171819" +
	"20212223242526272829" +
	"30313233343536373839" +
	"40414243444546474849" +
	"50515253545556575859" +
	"60616263646566676869" +
	"70717273747576777879" +
	"80818283848586878889" +
	"90919293949596979899"

const host32bit = ^uint(0)>>32 == 0

const digits = "0123456789abcdefghijklmnopqrstuvwxyz"

// formatBits计算给定基中u的字符串表示形式。
// 如果设置了neg，u将被视为负int64值。如果append_u是
// 集，则字符串被追加到dst，结果字节片是
// 作为第一个结果值返回；否则该字符串将返回
// 作为第二个结果值。
// 
func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) {
	if base < 2 || base > len(digits) {
		panic("strconv: illegal AppendInt/FormatInt base")
	}
	// 2<=base and&base<=len（数字）

	var a [64 + 1]byte // /+1表示基2中64位值的符号
	i := len(a)

	if neg {
		u = -u
	}

	// /转换位
	// 我们尽可能使用uint值，因为即使在32位机器上，这些值也将
	// 装入单个寄存器。
	if base == 10 {
		// 常见情况：使用常量表示/因为
		// 编译器可以将其优化为乘法+移位

		if host32bit {
			// 使用32位操作转换低位
			for u >= 1e9 {
				// 除了q=a/b 
				// 之外，避免使用r=a%b，因为64位除法和模运算
				// 是由上的运行时函数计算的32位机器。
				q := u / 1e9
				us := uint(u - q*1e9) // u%1e9适合单位
				for j := 4; j > 0; j-- {
					is := us % 100 * 2
					us /= 100
					i -= 2
					a[i+1] = smallsString[is+1]
					a[i+0] = smallsString[is+0]
				}

				// us<10，因为它包含首个9位us的最后一位
				// 。
				i--
				a[i] = smallsString[us*2+1]

				u = q
			}
			// u<1e9 
		}

		// u保证适合单元
		us := uint(u)
		for us >= 100 {
			is := us % 100 * 2
			us /= 100
			i -= 2
			a[i+1] = smallsString[is+1]
			a[i+0] = smallsString[is+0]
		}

		// us<100 
		is := us * 2
		i--
		a[i] = smallsString[is+1]
		if us >= 10 {
			i--
			a[i] = smallsString[is]
		}

	} else if isPowerOfTwo(base) {
		// 使用移位和遮罩，而不是/和%。
		// Base是2的幂，2<=Base<=len（数字），其中len（数字）是36。
		// 小于或等于36的2的最大幂为32，即1<5；
		// 也就是说，最大可能的移位计数是5。通过用
		// 常数7&-ind该值，我们告诉编译器移位计数总是
		// 小于8，小于任何寄存器宽度。这允许编译器为移位操作生成更好的代码。
		shift := uint(bits.TrailingZeros(uint(base))) & 7
		b := uint64(base)
		m := uint(base) - 1 // /==1<<shift-1 
		for u >= b {
			i--
			a[i] = digits[uint(u)&m]
			u >>= shift
		}
		// /u<base 
		i--
		a[i] = digits[uint(u)]
	} else {
		// 一般情况
		b := uint64(base)
		for u >= b {
			i--
			// 避免在q=a/b 
			// 之外使用r=a%b，因为64位除法和模运算
			// 是由32位机器上的运行时函数计算的。
			q := u / b
			a[i] = digits[uint(u-q*b)]
			u = q
		}
		// u<基本
		i--
		a[i] = digits[uint(u)]
	}

	// 添加符号（如果有）
	if neg {
		i--
		a[i] = '-'
	}

	if append_ {
		d = append(dst, a[i:]...)
		return
	}
	s = string(a[i:])
	return
}

func isPowerOfTwo(x int) bool {
	return x&(x-1) == 0
}
